package cn.iocoder.yudao.module.wms.service.pomain;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.ActHiProcinstMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.wms.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.wms.dal.redis.serialNumber.WmsSerialNumberRedisDAO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.wms.controller.admin.pomain.vo.*;
import cn.iocoder.yudao.module.wms.dal.dataobject.pomain.PomainDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.pomain.PomainsDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.wms.dal.mysql.pomain.PomainMapper;
import cn.iocoder.yudao.module.wms.dal.mysql.pomain.PomainsMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*;

/**
 * 采购订单主 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class PomainServiceImpl implements PomainService {
    /**
     * OA 对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "pomain-flowable";

    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private PomainMapper pomainMapper;
    @Resource
    private PomainsMapper pomainsMapper;
    @Resource
    private ActHiProcinstMapper actHiProcinstMapper;
    @Resource
    private WmsSerialNumberRedisDAO serialNumberRedisDAO;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createPomain(PomainSaveReqVO createReqVO) {
        // 插入
        String serialNumber = serialNumberRedisDAO.generate(WmsSerialNumberRedisDAO.POMAIN_SERIAL_PREFIX, RedisKeyConstants.SERIALPO);
        PomainDO pomain = BeanUtils.toBean(createReqVO, PomainDO.class,in -> in.setCode(serialNumber))
                .setStatus(BpmTaskStatusEnum.SUBMIT.getStatus()).setSum(getSum(createReqVO)).setRkSum(0.0);
        validateUserForCreateOrUpdate(pomain);
        pomainMapper.insert(pomain);

        // 插入子表
        createPomainsList(pomain.getId(), createReqVO.getPomainss());
        // 返回
        return pomain.getId();
    }
    @Override
    public void process(Integer pomainId)
    {
        /***
         * 启动流程
         */

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(SecurityFrameworkUtils.getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(pomainId)));

        // 将工作流的编号，更新到 业务表单中
        pomainMapper.updateById(new PomainDO().setId(pomainId).setProcessInstanceId(processInstanceId).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()));
        //将链接加入到ACT_HI_PROCINST表中
        actHiProcinstMapper.updateURLById("/order/pomainForm?id="+pomainId,processInstanceId);
    }

    @Override
    public List<PomainsRespVO> getPomainsOperateListByParams(PomainsRespVO pomainsRespVO) {
        return pomainMapper.getPomainsOperateListByParams(pomainsRespVO);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePomain(PomainSaveReqVO updateReqVO) {
        // 校验存在
        validatePomainExists(updateReqVO.getId());

        if (updateReqVO.getPomainss()!=null){
            // 更新
            PomainDO updateObj = BeanUtils.toBean(updateReqVO, PomainDO.class).setSum(getSum(updateReqVO));

            pomainMapper.updateById(updateObj);
            // 更新子表
            updatePomainsList(updateReqVO.getId(), updateReqVO.getPomainss());
        }else {
            // 更新
            PomainDO updateObj = BeanUtils.toBean(updateReqVO, PomainDO.class);
            pomainMapper.updateById(updateObj);
        }

    }

    private Double getSum(PomainSaveReqVO pomainSaveReqVO)
    {
        //得到总数量
        Double sum=0.0;
        if (pomainSaveReqVO.getPomainss()!=null){
            for (PomainsDO pomainsDO:pomainSaveReqVO.getPomainss())
            {
                sum+=pomainsDO.getQty();
            }
        }
        return sum;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePomain(Integer id) {
        // 校验存在
        validatePomainExists(id);
        // 删除
        pomainMapper.deleteById(id);

        // 删除子表
        deletePomainsByPid(id);
    }

    private void validatePomainExists(Integer id) {
        if (pomainMapper.selectById(id) == null) {
            throw exception(POMAIN_NOT_EXISTS);
        }
    }

    @Override
    public PomainDO getPomain(Integer id) {
        return pomainMapper.selectById(id);
    }

    @Override
    public PageResult<PomainDO> getPomainPage(PomainPageReqVO pageReqVO) {
        return pomainMapper.selectPage(pageReqVO);
    }

    // ==================== 子表（采购订单子） ====================

    @Override
    public List<PomainsDO> getPomainsListByPid(Integer pid) {
        return pomainsMapper.selectListByPid(pid);
    }

    @Override
    public void updatePomainStatus(PomainSaveReqVO pomainSaveReqVO) {
        pomainMapper.updatePomainStatus(pomainSaveReqVO);
    }

    @Override
    public PomainDO findByProcessInstanceId(String processInstanceId) {
        return pomainMapper.findByProcessInstanceId(processInstanceId);
    }

    private void createPomainsList(Integer pid, List<PomainsDO> list) {
        list.forEach(o -> o.setPid(pid));
        pomainsMapper.insertBatch(list);
    }

    private void updatePomainsList(Integer pid, List<PomainsDO> list) {
        deletePomainsByPid(pid);
		list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createPomainsList(pid, list);
    }

    private void deletePomainsByPid(Integer pid) {
        pomainsMapper.deleteByPid(pid);
    }

    /***
     * 业务处理
     * @param pomainDO
     * @param pomainsDOList
     */
    public void businessProcessing(PomainDO pomainDO,List<PomainsDO> pomainsDOList)
    {


    }

    @Override
    public List<PomainsRespVO> findPomainsByPid(Integer pid) {
        return pomainMapper.findPomainsByPid(pid);
    }

    @Override
    public List<PomainRespVO> list(PomainPageReqVO pageReqVO) {
        List<PomainDO> pomainDOS = pomainMapper.findPomainOperateList();
        return pomainDOS.stream()
                .map(this::convertToRespVO)
                .collect(Collectors.toList());
    }

    @Override
    public PomainsRespVO findPomainsById(Integer id) {
        return pomainMapper.findPomainsById(id);
    }

    @Override
    public void updatePomains(PomainsRespVO pomainsDO) {
        pomainMapper.updatePomains(pomainsDO);
    }

    @Override
    public List<PomainsRespVO> findPomainsOperateList(Integer pid) {
        return pomainMapper.findPomainsOperateList(pid);
    }


    /***
     * 数据校验
     */
    public void validateUserForCreateOrUpdate(PomainDO pomainDO)
    {
        if (pomainMapper.findCountByCode(pomainDO.getCode())>0)
        {
            throw exception(POMAIN_NOT_EXISTS_CODE);
        }
    }

    private PomainRespVO convertToRespVO(PomainDO pomainDO) {
        PomainRespVO respVO = new PomainRespVO();
        respVO.setId(pomainDO.getId());
        respVO.setCode(pomainDO.getCode());
        respVO.setCpersonId(pomainDO.getCpersonId());
        respVO.setCdepId(pomainDO.getCdepId());
        respVO.setCvenId(pomainDO.getCvenId());
        respVO.setDdate(pomainDO.getDdate());
        respVO.setCmemo(pomainDO.getCmemo());
        respVO.setCheckTime(pomainDO.getCheckTime());
        respVO.setCheckBy(pomainDO.getCheckBy());
        respVO.setStatus(pomainDO.getStatus());
        respVO.setProcessInstanceId(pomainDO.getProcessInstanceId());
        respVO.setSum(pomainDO.getSum());
        respVO.setRkSum(pomainDO.getRkSum());
        return respVO;
    }


}